﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using Dukou.Utils;

namespace Dukou.Search
{
    /// <summary>
    /// 搜索上下文
    /// </summary>
    [Serializable]
    public class SearchContext : ISearchContext
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="contentType"></param>
        public SearchContext(string contentType)
        {
            this.ContentType = contentType;
            this.Filters = new List<ISearchFilter>();
            this.Orders = new List<SearchOrder>();
        }

        /// <summary>
        /// 获取 内容类型
        /// </summary>
        public string ContentType { get; private set; }

        /// <summary>
        /// 获取 分页大小
        /// </summary>
        public int PageSize { get; private set; }

        /// <summary>
        /// 获取 当前页序号，下标从 1 开始
        /// </summary>
        public int PageIndex { get; private set; }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="size"></param>
        /// <returns></returns>
        public ISearchContext SetPageSize(int size)
        {
            this.PageSize = size;
            return this;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        public ISearchContext SetPageIndex(int index)
        {
            this.PageIndex = index;
            return this;
        }

        /// <summary>
        /// 
        /// </summary>
        public IList<ISearchFilter> Filters { get; private set; }

        /// <summary>
        /// 
        /// </summary>
        public IList<SearchOrder> Orders { get; private set; }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="filterName"></param>
        private void RemoveFilter(string filterName)
        {
            ISearchFilter filter = this.Filters.Where(x => x.FilterName == filterName).FirstOrDefault();
            if (filter != null)
            {
                this.Filters.Remove(filter);
            }
        }
        
        /// <summary>
        /// 
        /// </summary>
        /// <param name="filterName"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public ISearchContext SetFilter(string filterName, object value)
        {
            this.RemoveFilter(filterName);
            this.Filters.Add(new TermValueSearchFilter(filterName, value));
            return this;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="fieldName"></param>
        /// <param name="minValue"></param>
        /// <param name="maxValue"></param>
        /// <returns></returns>
        public ISearchContext SetFilter(string filterName, object minValue, object maxValue)
        {
            this.RemoveFilter(filterName);
            this.Filters.Add(new RangeValueSearchFilter(filterName, minValue, maxValue));
            return this;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="filterName"></param>
        /// <returns></returns>
        public T GetValue<T>(string filterName)
        {
            ISearchFilter filter = this.Filters.Where(x => x.FilterName == filterName).FirstOrDefault();
            if (filter == null)
            {
                return default(T);
            }

            TermValueSearchFilter term = filter as TermValueSearchFilter;
            if (term == null)
            {
                return default(T);
            }

            object v = TypeConverterUtil.Convert(term.Value, typeof(T));
            if (v == null)
            {
                return default(T);
            }

            return (T)v;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="filterName"></param>
        /// <returns></returns>
        public T GetMinValue<T>(string filterName)
        {
            ISearchFilter filter = this.Filters.Where(x => x.FilterName == filterName).FirstOrDefault();
            if (filter == null)
            {
                return default(T);
            }

            RangeValueSearchFilter term = filter as RangeValueSearchFilter;
            if (term == null)
            {
                return default(T);
            }

            object v = TypeConverterUtil.Convert(term.MinValue, typeof(T));
            if (v == null)
            {
                return default(T);
            }

            return (T)v;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="filterName"></param>
        /// <returns></returns>
        public T GetMaxValue<T>(string filterName)
        {
            ISearchFilter filter = this.Filters.Where(x => x.FilterName == filterName).FirstOrDefault();
            if (filter == null)
            {
                return default(T);
            }

            RangeValueSearchFilter term = filter as RangeValueSearchFilter;
            if (term == null)
            {
                return default(T);
            }

            object v = TypeConverterUtil.Convert(term.MaxValue, typeof(T));
            if (v == null)
            {
                return default(T);
            }

            return (T)v;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="filterName"></param>
        private void RemoveOrder(string filterName)
        {
            SearchOrder searchOrder = this.Orders.Where(x => x.FilterName == filterName).FirstOrDefault();
            if (searchOrder != null)
            {
                this.Orders.Remove(searchOrder);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="filterName"></param>
        /// <returns></returns>
        public ISearchContext SetOrder(string filterName)
        {
            return SetOrder(filterName, true);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="filterName"></param>
        /// <param name="asc"></param>
        /// <returns></returns>
        public ISearchContext SetOrder(string filterName, bool asc)
        {
            this.RemoveOrder(filterName);

            this.Orders.Add(new SearchOrder(filterName, asc));

            return this;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="filterName"></param>
        /// <returns></returns>
        public SearchOrder GetOrder(string filterName)
        {
            return this.Orders.Where(x=>x.FilterName == filterName).FirstOrDefault();
        }
    }
}
